package com.dkd.flow.strategy.service.operation;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dkd.common.core.domain.entity.SysUser;
import com.dkd.common.enums.UpdateType;
import com.dkd.common.utils.EbUtils;
import com.dkd.flow.domain.EProcessDefinition;
import com.dkd.flow.domain.EProcessInstances;
import com.dkd.flow.domain.EProcessTask;
import com.dkd.flow.emums.FlowStatus;
import com.dkd.flow.emums.NodeType;
import com.dkd.flow.emums.TaskActionType;
import com.dkd.flow.emums.TaskStatus;
import com.dkd.flow.mapper.EProcessDefinitionMapper;
import com.dkd.flow.mapper.EProcessInstancesMapper;
import com.dkd.flow.mapper.EProcessTaskMapper;
import com.dkd.flow.rules.BaseRules;
import com.dkd.flow.rules.conditions.ConditionsRule;
import com.dkd.flow.strategy.CommonStrategy;
import com.dkd.flow.utils.NodeUtils;
import com.dkd.flow.utils.TaskCreate;
import com.dkd.system.service.impl.SysUserServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public abstract class BaseStrategy implements CommonStrategy {
    static final Logger log = LoggerFactory.getLogger(BaseStrategy.class);
    @Autowired
    TaskCreate taskCreate;
    @Autowired
    EProcessInstancesMapper eProcessInstancesMapper;
    @Autowired
    public EProcessTaskMapper eProcessTaskMapper;
    @Autowired
    ConditionsRule conditionsRule;
    @Autowired
    BaseRules baseRules;
    @Autowired
    public NodeUtils nodeUtils;
    @Autowired
    public SysUserServiceImpl sysUserServiceImpl;
    @Autowired
    EProcessDefinitionMapper eProcessDefinitionMapper;
    // 节点关系
    public JSONObject relations;
    // 节点
    public ArrayList<JSONObject> nodes;
    // 关系
    public ArrayList<JSONObject> links;

    void clear() {
        relations = null;
        nodes = null;
        links = null;
    }

    // 审批流程的时候，更新实例
    public EProcessInstances updateEProcessInstances(EProcessInstances paramsEProcessInstances) {
        EbUtils.updateTableFields(UpdateType.ADD_FIELD,
                paramsEProcessInstances);
        Integer eProcessInstancesResult = eProcessInstancesMapper.updateById(paramsEProcessInstances);
        if (eProcessInstancesResult <= 0) {
            throw new RuntimeException("更新失败");
        }
        return eProcessInstancesMapper.selectById(paramsEProcessInstances.getID());
    }

    // 重置实例节点审批人数量
    public void resetEProcessInstancesApproverCount(EProcessInstances eProcessInstances,
            String processDesignId,
            Integer requiredApproverAccount) {
        // 更新流程实例, 设置流程实例的审批总数和当前审批总数为0
        eProcessInstances.setRequiredApprovalCount(nodeUtils.getRequiredApprovalCount(processDesignId));
        eProcessInstances.setNodeApprovedCount(requiredApproverAccount);
        updateEProcessInstances(eProcessInstances);
    }

    // 发起流程的时候，创建实例实例
    public EProcessInstances createEProcessInstances(EProcessInstances paramsEProcessInstances,
            FlowStatus flowStatus,
            Long _processInstancesId) {
        // 从草稿过来的，会有processInstancesId
        Long processInstanceId = _processInstancesId;
        if (processInstanceId == null) {
            processInstanceId = IdUtil.getSnowflakeNextId();
        }
        EProcessDefinition eProcessDefinition = eProcessDefinitionMapper
                .selectById(paramsEProcessInstances.getProcessDefinitionId());
        paramsEProcessInstances.setID(processInstanceId);
        // 设置流程状态
        paramsEProcessInstances.setFlowStatus(flowStatus.getValue().longValue());
        // FlowType设置，套件，暂时不做处理
        // paramsEProcessInstances.setFlowType(FlowType.);
        SysUser liableUser = nodeUtils.getLiableUser(paramsEProcessInstances);
        paramsEProcessInstances.setSubmitter(liableUser.getUserId());
        paramsEProcessInstances.setTitle(eProcessDefinition.getFlowName());
        EbUtils.setCreateByIfNull(paramsEProcessInstances,
                EProcessInstances::getCreateBy,
                EProcessInstances::setCreateBy);
        EbUtils.updateTableFields(UpdateType.ADD_FIELD,
                paramsEProcessInstances);
        Integer eProcessInstancesResult = eProcessInstancesMapper.insert(paramsEProcessInstances);
        if (eProcessInstancesResult <= 0) {
            throw new RuntimeException("流程实例插入数据库失败");
        }
        return eProcessInstancesMapper.selectById(paramsEProcessInstances.getID());
    }

    // 初始化节点关系，都是从nodeUtils.initRelationsByData(processDefinitionId)中获取的。
    void initNodeRelations(Long processDefinitionId) {
        relations = nodeUtils.initRelationsByData(processDefinitionId);
        nodes = (ArrayList<JSONObject>) relations.get("nodes");
        links = (ArrayList<JSONObject>) relations.get("links");
        if (links.isEmpty()) {
            throw new RuntimeException("links 列表为空，无法继续执行");
        }
    }

    // 处理下一个节点
    String processDesignId = null;

    public String handlerNextNode(String curTaskNodeId,
            JSONObject formValue,
            EProcessInstances eProcessInstances,
            ArrayList<JSONObject> links,
            EProcessTask curTask,
            Long taskGroupId,
            TaskActionType taskActionType,
            Long actionTaskId) {
        ArrayList<JSONObject> toList = nodeUtils.getRelatedNodes(links, curTaskNodeId);
        if (toList.size() > 0) {
            JSONObject nextNode = toList.get(0).getJSONObject("toNode");
            NodeType nodeType = nodeUtils.getToNodeType(nextNode);
            switch (nodeType) {
                case CONDITION: {
                    baseRules.register(formValue);
                    for (JSONObject node : toList) {
                        JSONObject conditionNode = node.getJSONObject("toNode");
                        baseRules.fire(conditionNode);
                    }
                    String resultConditionNodeId = baseRules.resultPick();
                    if (resultConditionNodeId != null) {
                        JSONObject matchedNode = findNodeById(resultConditionNodeId, toList);
                        if (matchedNode != null) {
                            // 递归查找下一个审批人节点
                            return handlerNextNode(matchedNode.getString("to"),
                                    formValue,
                                    eProcessInstances,
                                    links,
                                    curTask,
                                    taskGroupId,
                                    taskActionType,
                                    actionTaskId);
                        }
                    }
                    break;
                }
                case APPROVER: {
                    for (JSONObject node : toList) {
                        JSONObject approverNode = node.getJSONObject("toNode");
                        // 创建审批人任务
                        taskCreate.createApproverTask(eProcessInstances,
                                approverNode,
                                (SysUser approver) -> {
                                    Long approverTaskId = IdUtil.getSnowflakeNextId();
                                    return taskCreate.approverTask(eProcessInstances,
                                            approver,
                                            node.getString("to"),
                                            TaskStatus.UNDER_APPROVAL,
                                            approverTaskId,
                                            actionTaskId,
                                            null,
                                            taskGroupId,
                                            JSONObject.toJSONString(formValue),
                                            taskActionType);
                                });
                        log.info("创建审批任务，节点：{}", approverNode);
                        // 返回下一个审批人节点的nodeId
                        return node.getString("to");
                    }
                    break;
                }
                case CC: {
                    for (JSONObject node : toList) {
                        JSONObject ccNode = node.getJSONObject("toNode");
                        Long ccTaskId = IdUtil.getSnowflakeNextId();
                        taskCreate.createCcTask(eProcessInstances,
                                ccNode,
                                ccTaskId,
                                actionTaskId,
                                null,
                                taskGroupId,
                                JSONObject.toJSONString(formValue),
                                taskActionType);
                        log.info("创建抄送任务，节点：{}",
                                ccNode);
                        String ccNodeId = ccNode.getString("nodeId");
                        handlerNextNode(ccNodeId,
                                formValue,
                                eProcessInstances,
                                links,
                                curTask,
                                taskGroupId,
                                taskActionType,
                                actionTaskId);
                    }
                    break;
                }
            }
        } else {
            processComplete(eProcessInstances, curTask);
        }
        return null;
    }

    // 根据nodeId查找节点
    private JSONObject findNodeById(String nodeId, ArrayList<JSONObject> nodes) {
        for (JSONObject node : nodes) {
            JSONObject toNode = node.getJSONObject("toNode");
            if (toNode.getString("nodeId").equals(nodeId)) {
                return node;
            }
        }
        return null;
    }

    public void updateTaskUpdateTime(Long tid) {
        EProcessTask curTask = eProcessTaskMapper.selectEProcessTaskByID(tid);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("TASK_GROUP_ID",
                curTask.getTaskGroupId());
        List<EProcessTask> eProcessTaskList = eProcessTaskMapper.selectList(queryWrapper);
        if (eProcessTaskList.size() > 0) {
            eProcessTaskList.stream().forEach(eProcessTask -> {
                EbUtils.updateTableFields(UpdateType.UPDATE_FIELD,
                        curTask);
                eProcessTaskMapper.updateById(curTask);
            });
        }
    }

    // 审批完成
    void processComplete(EProcessInstances eProcessInstances,
            EProcessTask curTask) {
        // 修改流程状态
        eProcessInstances.setFlowStatus(FlowStatus.COMPLETE.getValue().longValue());
        // 设置流程完成时间
        eProcessInstances.setCompletionTime(new Date());
        EbUtils.updateTableFields(UpdateType.UPDATE_FIELD,
                eProcessInstances);
        eProcessInstancesMapper.updateEProcessInstances(eProcessInstances);
    }

    @Transactional
    @Override
    public abstract Long execute(JSONObject data);
}